from fastapi.security import OAuth2PasswordBearer
from typing import Annotated
from passlib.context import CryptContext
from pydantic import BaseModel
from fastapi import Depends, HTTPException, status
from jwt import PyJWTError
from app.utils.jwt import check_token

# 密码hash上下文
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# 模拟数据库
fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": pwd_context.hash("secret"),
        "disabled": False,
    }
}



oauth2_scheme:OAuth2PasswordBearer = OAuth2PasswordBearer(tokenUrl="/token")


class User(BaseModel):
    username: str
    email: str | None = None
    full_name: str | None = None
    disabled: bool | None = None

class UserInDB(User):
    hashed_password: str

# 通过用户名查询用户
def get_user(db, username: str):
    if username in db:
        # 查询数据库
        user_dict = db[username]
        return UserInDB(**user_dict)



# 验证密码
def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)


# 生成用户的hash密码(创建用户的时候用)
def get_password_hash(password):
    return pwd_context.hash(password)

# 验证用户密码
def authenticate_user(fake_db, username: str, password: str):
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user



class TokenData(BaseModel):
    username: str | None = None
# 认证依赖项
async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = check_token(token)
        username: str = payload.get("username")
        if username is None:
            raise credentials_exception
        # 数据校验
        token_data = TokenData(username=username)
    except PyJWTError:
        raise credentials_exception
    user = get_user(fake_users_db, username=token_data.username)
    if user is None:
        raise credentials_exception
    return user


async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user


